package mategrafica

import javafx.{event => jfxe, collections => jfxc}
import javafx.scene.{chart => jfxsc}

import mathFrame.Arithmetic
import mathFrame.JimParsers._
import mathFrame.JimParsers
import mathFrame.NoValue
import mathFrame.Parameter
import mathFrame.Plotter2D
import mathFrame.Trigonometry
import mathFrame.UserFunction1P

import scalafx.Includes._
import scalafx.application.JFXApp
import scalafx.collections._
import scalafx.scene.Scene
import scalafx.scene.chart._
import scalafx.scene.control._
import scalafx.scene.layout._
import scalafx.stage.Stage

object MainO extends JFXApp {
  Trigonometry.init
  Arithmetic.init
  val x = new Parameter("x")
  stage = new Stage {
    title = "Mategráfica"
  }
  val scene = new Scene(400, 400)
  stage.scene = scene
  val content = new BorderPane
  scene.content = content
  val plotter = new Plotter2D(200, 200)
  val label = new Label {
    text = "f(x) = "
  }
  val edit: TextField = new TextField {
    prefWidth = 200
  }
  val actionHandler = new jfxe.EventHandler[jfxe.ActionEvent] {
    def handle(e: jfxe.ActionEvent) = {
      JimParsers.parseExpr(edit.getText, x) match {
        case Success(tree, _) => plotter.function = new UserFunction1P("", x, tree)
        case Failure(msg, _) => {
            println(msg)
            plotter.function = NoValue
        }
      }
      plotter.regenerate
    }
  }
  edit.onAction = actionHandler
  val parse = new Button {
    text = "Parse"
    onAction = actionHandler
  }
  val top =  new HBox {
    content += label
    content += edit
    content += parse
  }
  content top = top
  content center = plotter
}

object Main extends JFXApp { //ScalaFxTest
  def createPetsAxis = {
    val petNames = new ObservableBuffer[String]()
    petNames += "Cats"
    petNames += "Dogs"
    petNames += "Others"
    val petsAxis = CategoryAxis(petNames)
    petsAxis.label = "Pets"
    petsAxis
  }
  
  def createPctOwnedAxis = {
    val pctOwnedAxis = NumberAxis(0.0, 1.0, 0.05)
    pctOwnedAxis.label = "% Owned"
    pctOwnedAxis
  }
  
  def createAgesAxis = {
    val ageAxis = NumberAxis(0, 100, 10)
    ageAxis.label = "Age"
    ageAxis
  }
  
  def createCountAxis = {
    val ageAxis = NumberAxis(0, 20, 4)
    ageAxis.label = "Count"
    ageAxis
  }
  
  def createPetsPctOwnedEuropeData = {
    val petData = new ObservableBuffer[jfxsc.XYChart.Data[String, Number]]()
    petData += XYChart.Data[String, Number]("Cats", .30)
    petData += XYChart.Data[String, Number]("Dogs", .25)
    petData += XYChart.Data[String, Number]("Others", .45)
    petData
  }
  
  def createPetsPctOwnedEuropeSeries = {
    val petData = createPetsPctOwnedEuropeData
    val petSeries = XYChart.Series[String, Number](petData)
    petSeries.name = "Europe"
    ObservableBuffer[jfxsc.XYChart.Series[String, Number]](petSeries)
  }
  
  def createPetsPctOwnedAmericaData = {
    val petData = new ObservableBuffer[jfxsc.XYChart.Data[String, Number]]()
    petData += XYChart.Data[String, Number]("Cats", .50)
    petData += XYChart.Data[String, Number]("Dogs", .45)
    petData += XYChart.Data[String, Number]("Others", .75)
    petData
  }
  
  def createTwoPetsPctOwnedSeries = {
    val petDataAmerica = createPetsPctOwnedAmericaData
    val petSeriesAmerica = XYChart.Series[String, Number](petDataAmerica)
    petSeriesAmerica.name = "America"
    var series = createPetsPctOwnedEuropeSeries
    series += petSeriesAmerica
    series
  }
  
  def createAgesPctOwnedEuropeData = {
    val petData = new ObservableBuffer[jfxsc.XYChart.Data[Number, Number]]()
    petData += XYChart.Data[Number, Number](15, .35)
    petData += XYChart.Data[Number, Number](21, .30)
    petData += XYChart.Data[Number, Number](25, .37)
    petData += XYChart.Data[Number, Number](50, .25)
    petData += XYChart.Data[Number, Number](58, .30)
    petData += XYChart.Data[Number, Number](75, .45)
    petData += XYChart.Data[Number, Number](80, .30)
    petData
  }
  
  def createAgesPctOwnedEuropeSeries = {
    val petData = createAgesPctOwnedEuropeData
    val petSeries = XYChart.Series[Number, Number](petData)
    petSeries.name = "Europe"
    ObservableBuffer[jfxsc.XYChart.Series[Number, Number]](petSeries)
  }
  
  def createAgesPctOwnedAmericaData = {
    val petData = new ObservableBuffer[jfxsc.XYChart.Data[Number, Number]]()
    petData += XYChart.Data[Number, Number](25, .35)
    petData += XYChart.Data[Number, Number](41, .30)
    petData += XYChart.Data[Number, Number](15, .37)
    petData += XYChart.Data[Number, Number](80, .25)
    petData += XYChart.Data[Number, Number](38, .30)
    petData += XYChart.Data[Number, Number](65, .45)
    petData += XYChart.Data[Number, Number](90, .30)
    petData
  }
  
  def createTwoAgesPctOwnedSeries = {
    val petDataTwo = createAgesPctOwnedAmericaData
    val petSeriesTwo = XYChart.Series[Number, Number](petDataTwo)
    petSeriesTwo.name = "America"
    var series = createAgesPctOwnedEuropeSeries
    series += petSeriesTwo
    series
  }
  
  def createAgesCountEuropeData = {
    val petData = new ObservableBuffer[jfxsc.XYChart.Data[Number, Number]]()
    petData += XYChart.Data[Number, Number](22, 45, 1)
    petData += XYChart.Data[Number, Number](76, 50, 4)
    petData += XYChart.Data[Number, Number](84, 30, 2)
    petData += XYChart.Data[Number, Number](14, 35, 5)
    petData += XYChart.Data[Number, Number](39, 30, 3)
    petData += XYChart.Data[Number, Number](55, 25, 2)
    petData
  }
  
  def createAgesCountEuropeSeries = {
    val petData = createAgesCountEuropeData
    val petSeries = XYChart.Series[Number, Number](petData)
    petSeries.name = "Europe"
    ObservableBuffer[jfxsc.XYChart.Series[Number, Number]](petSeries)
  }
  
  def createAgesCountAmericaData = {
    val petData = new ObservableBuffer[jfxsc.XYChart.Data[Number, Number]]()
    petData += XYChart.Data[Number, Number](31, 45, 4)
    petData += XYChart.Data[Number, Number](35, 50, 6)
    petData += XYChart.Data[Number, Number](50, 30, 2)
    petData += XYChart.Data[Number, Number](55, 35, 1)
    petData += XYChart.Data[Number, Number](80, 30, 5)
    petData += XYChart.Data[Number, Number](85, 25, 4)
    petData
  }
  
  def createTwoAgesCountSeries = {
    val petDataTwo = createAgesCountAmericaData
    val petSeriesTwo = XYChart.Series[Number, Number](petDataTwo)
    petSeriesTwo.name = "America"
    var series = createAgesCountEuropeSeries
    series += petSeriesTwo
    series
  }
  
  def createPieChart = {
    val pieChartData = new ObservableBuffer[jfxsc.PieChart.Data]()
    pieChartData += PieChart.Data("Cats", .30)
    pieChartData += PieChart.Data("Dogs", .25)
    pieChartData += PieChart.Data("Others", .45)
    val pieChart = PieChart(pieChartData)
    pieChart.prefWidth = 240
    pieChart.prefHeight = 240
    pieChart.title = "Pie Chart"
    pieChart.legendVisible = false
    pieChart
  }
  
  def createAreaChart = {
    val petNamesAxis = createPetsAxis
    val petNumbersAxis = createPctOwnedAxis
    val series = createTwoPetsPctOwnedSeries
    val areaChart = AreaChart[String, Number](petNamesAxis, petNumbersAxis, series)
    areaChart.prefWidth = 240
    areaChart.prefHeight = 240
    areaChart.title = "Area Chart"
    areaChart
  }
  
  def createBarChart = {
    val petNamesAxis = createPetsAxis
    val petNumbersAxis = createPctOwnedAxis
    val series = createTwoPetsPctOwnedSeries
    val barChart = BarChart[String, Number](petNamesAxis, petNumbersAxis, series)
    barChart.prefWidth = 240
    barChart.prefHeight = 240
    barChart.title = "Bar Chart"
    barChart
  }
  
  def createBubbleChart = {
    val petNumbers1Axis = createAgesAxis
    val petNumbers2Axis = createCountAxis
    val series = createTwoAgesCountSeries
    val bubbleChart = BubbleChart[Number, Number](petNumbers1Axis, petNumbers2Axis, series)
    bubbleChart.prefWidth = 240
    bubbleChart.prefHeight = 240
    bubbleChart.title = "Bubble Chart"
    bubbleChart
  }

  def createLineChart = {
    val petNamesAxis = createPetsAxis
    val petNumbersAxis = createPctOwnedAxis
    val series = createPetsPctOwnedEuropeSeries
    val lineChart = LineChart[String, Number](petNamesAxis, petNumbersAxis, series)
    lineChart.prefWidth = 240
    lineChart.prefHeight = 240
    lineChart.title = "Line Chart"
    lineChart
  }
  
  def createScatterChart = {
    val petNamesAxis = createPetsAxis
    val petNumbersAxis = createPctOwnedAxis
    val series = createPetsPctOwnedEuropeSeries
    val scatterChart = ScatterChart[String, Number](petNamesAxis, petNumbersAxis, series)
    scatterChart.prefWidth = 240
    scatterChart.prefHeight = 240
    scatterChart.title = "Scatter Chart"
    scatterChart
  }
  
  def createStackedAreaChart = {
    val petNumbers1Axis = createAgesAxis
    val petNumbers2Axis = createPctOwnedAxis
    val series = createTwoAgesPctOwnedSeries
    val stackedAreaChart = StackedAreaChart[Number, Number](petNumbers1Axis, petNumbers2Axis, series)
    stackedAreaChart.prefWidth = 240
    stackedAreaChart.prefHeight = 240
    stackedAreaChart.title = "Stacked Area Chart"
    stackedAreaChart
  }
  
  def createStackedBarChart = {
    val petNamesAxis = createPetsAxis
    val petNumbersAxis = createPctOwnedAxis
    val series = createTwoPetsPctOwnedSeries
    val stackedBarChart = StackedBarChart[String, Number](petNamesAxis, petNumbersAxis, series)
    stackedBarChart.prefWidth = 240
    stackedBarChart.prefHeight = 240
    stackedBarChart.title = "Stacked Bar Chart"
    stackedBarChart
  }
  
    stage = new Stage {
    title = "ScalaFX Charts"
  }
  val scene = new Scene(500, 500)
  stage.scene = scene
  val content = new TilePane
  val scroll = new ScrollPane
  scroll.prefWidth = 500
  scroll.prefHeight = 500
  scroll.content = content
  scene.content = scroll
  content.prefColumns = 2
  content.children += createPieChart
  content.children += createAreaChart
  content.children += createBarChart
  content.children += createBubbleChart
  content.children += createLineChart
  content.children += createScatterChart
  content.children += createStackedAreaChart
  content.children += createStackedBarChart
}

object MainMg4jTest { //Mg4jTest
  def main(args: Array[String]): Unit = {
    Trigonometry.init
    Arithmetic.init
    JimParsers.testExpr("123")
    JimParsers.testExpr("12 + 34")
    JimParsers.testExpr("2 - 1")
    JimParsers.testExpr("1 + 2 + 3 - 4")
    JimParsers.testExpr("3 + 4 * 5")
    JimParsers.testExpr("(3 + 4) * 5")
    JimParsers.testExpr("3*-(2+2)")
    JimParsers.testExpr("123.456")
    JimParsers.testExpr("1.2+3")
    JimParsers.testExpr("5e-1 + 2")
    JimParsers.test("const e = 2.71828183")
    JimParsers.test("var x")
    JimParsers.test("var y = 1")
    JimParsers.testFail("const x = 3")
    JimParsers.test("def f(x) = sin(x)")
    JimParsers.testExpr("sin(pi/2)")
    JimParsers.test("def g(x) = f(2*x)")
    JimParsers.testExpr("g(2)")
  }
}

